home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
language
/
asxsrc.arc
/
LKMAIN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-08-25
|
9KB
|
547 lines
/* lkmain.c */
/*
* (C) Copyright 1989
* All Rights Reserved
*
* Alan R. Baldwin
* 721 Berkeley St.
* Kent, Ohio 44240
*/
#include <stdio.h>
#include "aslink.h"
VOID
main(argc, argv)
char *argv[];
{
register char *p;
register c, i;
FILE *afile();
pflag = 1;
startp = (struct lfile *) new (sizeof (struct lfile));
for (i=1; i<argc; ++i) {
p = argv[i];
if (*p == '-') {
while (ctype[c = *(++p)] == LETTER) {
switch(c) {
case 'c':
case 'C':
startp->f_type = F_STD;
break;
case 'f':
case 'F':
startp->f_type = F_LNK;
break;
case 'n':
case 'N':
pflag = 0;
break;
case 'p':
case 'P':
pflag = 1;
break;
default:
usage();
}
}
} else {
if (startp->f_type == F_LNK) {
startp->f_idp = p;
}
}
}
if (startp->f_type == NULL)
usage();
if (startp->f_type == F_LNK && startp->f_idp == NULL)
usage();
cfp = NULL;
sfp = NULL;
filep = startp;
while (1) {
ip = ib;
if (getline() == 0)
break;
if (pflag && sfp != stdin)
fprintf(stdout, "%s\n", ip);
if (*ip == NULL || parse())
break;
}
fclose(sfp);
if (linkp == NULL)
usage();
syminit();
for (pass=0; pass<2; ++pass) {
cfp = NULL;
sfp = NULL;
filep = linkp;
hp = NULL;
radix = 10;
while (getline()) {
ip = ib;
link();
}
if (pass == 0) {
/*
* Set area base addresses.
*/
setbas();
/*
* Link all area addresses.
*/
lnkarea();
/*
* Process global definitions.
*/
setgbl();
/*
* Check for undefined globals.
*/
symdef(stderr);
/*
* Output Link Map.
*/
if (mflag)
map();
/*
* Open output file
*/
if (oflag == 1)
ofp = afile(linkp->f_idp, "ihx", 1);
if (oflag == 2)
ofp = afile(linkp->f_idp, "s19", 1);
} else {
reloc('E');
}
}
}
VOID
link()
{
register c;
if ((c=endline()) == 0) { return; }
switch (c) {
case 'X':
radix = 16;
break;
case 'D':
radix = 10;
break;
case 'Q':
radix = 8;
break;
case 'H':
if (pass == 0) {
newhead();
} else {
if (hp == 0) {
hp = headp;
} else {
hp = hp->h_hp;
}
}
break;
case 'M':
if (pass == 0)
module();
break;
case 'A':
if (pass == 0)
newarea();
break;
case 'S':
if (pass == 0)
newsym();
break;
case 'T':
case 'R':
if (pass == 0)
break;
reloc(c);
break;
default:
break;
}
if (c == 'X' || c == 'D' || c == 'Q') {
if ((c = get()) == 'H') {
hilo = 1;
} else
if (c == 'L') {
hilo = 0;
}
}
}
VOID
map()
{
register i;
register struct head *hdp;
/*
* Open Map File
*/
mfp = afile(linkp->f_idp, "map", 1);
/*
* Output Map Area Lists
*/
page = 0;
lop = NLPP;
slew(mfp);
ap = areap;
while (ap) {
lstarea(ap);
ap = ap->a_ap;
}
/*
* List Linked Files
*/
newpag(mfp);
fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
hdp = headp;
filep = linkp;
while (filep) {
fprintf(mfp, "%-16s", filep->f_idp);
i = 0;
while (hdp->h_lfile == filep) {
if (i % 5) {
fprintf(mfp, ", %8.8s", hdp->m_id);
} else {
if (i) {
fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
} else {
fprintf(mfp, " [ %8.8s", hdp->m_id);
}
}
hdp = hdp->h_hp;
i++;
}
if (i)
fprintf(mfp, " ]");
fprintf(mfp, "\n");
filep = filep->f_flp;
}
/*
* List Base Address Definitions
*/
if (basep) {
newpag(mfp);
fprintf(mfp, "\nUser Base Address Definitions\n\n");
bsp = basep;
while (bsp) {
fprintf(mfp, "%s\n", bsp->b_strp);
bsp = bsp->b_base;
}
}
/*
* List Global Definitions
*/
if (globlp) {
newpag(mfp);
fprintf(mfp, "\nUser Global Definitions\n\n");
gsp = globlp;
while (gsp) {
fprintf(mfp, "%s\n", gsp->g_strp);
gsp = gsp->g_globl;
}
}
fprintf(mfp, "\n\f");
symdef(mfp);
fclose(mfp);
}
int
parse()
{
register c;
char fid[NINPUT];
while (c = getnb()) {
if ( c == '-') {
while (ctype[c=get()] == LETTER) {
switch(c) {
case 'i':
case 'I':
oflag = 1;
break;
case 's':
case 'S':
oflag = 2;
break;
case 'm':
case 'M':
++mflag;
break;
case 'x':
case 'X':
xflag = 0;
break;
case 'q':
case 'Q':
xflag = 1;
break;
case 'd':
case 'D':
xflag = 2;
break;
case 'e':
case 'E':
return(1);
case 'n':
case 'N':
pflag = 0;
break;
case 'p':
case 'P':
pflag = 1;
break;
case 'b':
case 'B':
bassav();
return(0);
case 'g':
case 'G':
gblsav();
return(0);
default:
fprintf(stderr, "Invalid option\n");
exit(1);
}
}
} else
if (ctype[c] == LETTER || ctype[c] == DIGIT) {
if (linkp == NULL) {
linkp = (struct lfile *)
new (sizeof (struct lfile));
lfp = linkp;
} else {
lfp->f_flp = (struct lfile *)
new (sizeof (struct lfile));
lfp = lfp->f_flp;
}
getfid(fid, c);
lfp->f_idp = (char *) new (strlen(fid)+1);
strcpy(lfp->f_idp, fid);
lfp->f_type = F_REL;
} else
if (c == ';') {
return(0);
} else
if (c == ',') {
;
} else {
fprintf(stderr, "Invalid input");
exit(1);
}
}
return(0);
}
/*
* Base string save
*/
VOID
bassav()
{
if (basep == NULL) {
basep = (struct base *)
new (sizeof (struct base));
bsp = basep;
} else {
bsp->b_base = (struct base *)
new (sizeof (struct base));
bsp = bsp->b_base;
}
unget(getnb());
bsp->b_strp = (char *) new (strlen(ip)+1);
strcpy(bsp->b_strp, ip);
}
VOID
setbas()
{
register v;
char id[NCPS];
bsp = basep;
while (bsp) {
ip = bsp->b_strp;
getid(id, -1);
if (getnb() == '=') {
v = expr(0);
for (ap = areap; ap != NULL; ap = ap->a_ap) {
if (symeq(id, ap->a_id))
break;
}
if (ap == NULL) {
fprintf(stderr,
"No definition of area %s\n", id);
} else {
ap->a_addr = v;
}
} else {
fprintf(stderr, "No '=' in base expression");
}
bsp = bsp->b_base;
}
}
/*
* Global string save
*/
VOID
gblsav()
{
if (globlp == NULL) {
globlp = (struct globl *)
new (sizeof (struct globl));
gsp = globlp;
} else {
gsp->g_globl = (struct globl *)
new (sizeof (struct globl));
gsp = gsp->g_globl;
}
unget(getnb());
gsp->g_strp = (char *) new (strlen(ip)+1);
strcpy(gsp->g_strp, ip);
}
VOID
setgbl()
{
register v;
register struct sym *sp;
char id[NCPS];
gsp = globlp;
while (gsp) {
ip = gsp->g_strp;
getid(id, -1);
if (getnb() == '=') {
v = expr(0);
sp = lkpsym(id, 0);
if (sp == NULL) {
fprintf(stderr,
"No definition of symbol %s\n", id);
} else {
if (sp->s_flag & S_DEF) {
fprintf(stderr,
"Redefinition of symbol %s\n", id);
sp->s_axp = NULL;
}
sp->s_addr = v;
sp->s_type |= S_DEF;
}
} else {
fprintf(stderr, "No '=' in global expression");
}
gsp = gsp->g_globl;
}
}
FILE *
afile(fn, ft, wf)
char *fn;
char *ft;
{
register char *p1, *p2, *p3;
register c;
FILE *fp;
char fb[FILSPC];
p1 = fn;
p2 = fb;
p3 = ft;
while ((c = *p1++) && c != '.') {
if (p2 < &fb[FILSPC-4])
*p2++ = c;
}
*p2++ = '.';
if (*p3 == 0) {
if (c == '.') {
p3 = p1;
} else {
p3 = "rel";
}
}
while (c = *p3++) {
if (p2 < &fb[FILSPC-1])
*p2++ = c;
}
*p2++ = 0;
if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
exit(1);
}
return (fp);
}
char *usetxt[] = {
"Startup:",
" -c Command line input",
" -f file [.lnk] File input",
"Usage: [-Options] file [file ...]",
" -p Prompt and echo of file.ln